/*
 * littlevgl_support.c
 *
 *  Created on: Aug 15, 2020
 *      Author: AN
 */

#include "littlevgl_support.h"
#include "lvgl.h"
#include "lv_conf.h"
#include "stm32412g_discovery_lcd.h"
#include "stm32412g_discovery_ts.h"
#include "stm32412g_discovery_qspi.h"
#include "Components\st7789h2\st7789h2.h"

#include <stdbool.h>


static bool DEMO_ReadTouch(lv_indev_drv_t * indev_drv, lv_indev_data_t *data);
static void DEMO_FlushDisplay(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p);

void lv_port_disp_init(void)
{
    /*-------------------------
     * Initialize your display
     * -----------------------*/
	BSP_LCD_Init();
	BSP_LCD_Clear(LCD_COLOR_WHITE);

    /*-----------------------------------
     * Register the display in LittlevGL
     *----------------------------------*/

    lv_disp_drv_t disp_drv;      /*Descriptor of a display driver*/
    lv_disp_drv_init(&disp_drv); /*Basic initialization*/

    /*Set up the functions to access to your display*/
    static lv_disp_buf_t disp_buf_2;
    static lv_color_t buf2_1[LV_HOR_RES_MAX * 240];                        /*A buffer for 10 rows*/
    static lv_color_t buf2_2[LV_HOR_RES_MAX * 240];                        /*An other buffer for 10 rows*/
    lv_disp_buf_init(&disp_buf_2, buf2_1, buf2_2, LV_HOR_RES_MAX * 240);   /*Initialize the display buffer*/
    disp_drv.buffer = &disp_buf_2;

    disp_drv.hor_res = LCD_WIDTH;
    disp_drv.ver_res = LCD_HEIGHT;

    /*Used in buffered mode (LV_VDB_SIZE != 0  in lv_conf.h)*/
    disp_drv.flush_cb = DEMO_FlushDisplay;

    /*Finally register the driver*/
    lv_disp_drv_register(&disp_drv);
}

void lv_port_indev_init(void)
{
    lv_indev_drv_t indev_drv;

    /*------------------
     * Touchpad
     * -----------------*/

    /*Initialize your touchpad */
    BSP_TS_InitEx(240, 240, TS_ORIENTATION_PORTRAIT);

    /*Register a touchpad input device*/
    lv_indev_drv_init(&indev_drv);
    indev_drv.type = LV_INDEV_TYPE_POINTER;
    indev_drv.read_cb = DEMO_ReadTouch;
    lv_indev_drv_register(&indev_drv);
}

typedef struct
{
  __IO uint16_t REG;
  __IO uint16_t RAM;
}LCD_CONTROLLER_TypeDef;
#define FMC_BANK1_BASE  ((uint32_t)(0x60000000 | 0x00000000))
#define FMC_BANK1       ((LCD_CONTROLLER_TypeDef *) FMC_BANK1_BASE)
static void DEMO_FlushDisplay(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
    //The most simple case (but also the slowest) to put all pixels to the screen one-by-one
//    BSP_LCD_DrawRGBImage(area->x1, area->y1, (area->x2-area->x1), (area->y2-area->y1), color_p);

    uint16_t Xpos = area->x1;
    uint16_t Ypos = area->y1;
    uint16_t Xsize = (area->x2-area->x1)+1;
    uint16_t Ysize = (area->y2-area->y1)+1;
    ST7789H2_SetDisplayWindow(Xpos, Ypos, Xsize, Ysize);
    uint32_t posY;
    uint32_t nb_line = 0;

    for (posY = Ypos; posY < (Ypos + Ysize); posY ++)
    {
      /* Set Cursor */
      ST7789H2_SetCursor(Xpos, posY);

      /* Prepare to write to LCD RAM */
      ST7789H2_WriteReg(ST7789H2_WRITE_RAM, (uint8_t*)NULL, 0);   /* RAM write data command */

      uint32_t i = 0;
      uint32_t posX;
      uint16_t *rgb565 = (uint16_t*)color_p + nb_line * (Xsize);
      for (posX = Xpos; posX < (Xsize + Xpos); posX++)
      {
    		  if (posX != (Xsize + Xpos))     /* When writing last pixel when size is odd, the third part is not written */
    		  {
    			  FMC_BANK1->RAM = (uint16_t)rgb565[i];
    			  __DSB();
    		  }
    		  i++;
      }

      nb_line++;
    }
    ST7789H2_SetDisplayWindow(0, 0, BSP_LCD_GetXSize(), BSP_LCD_GetYSize());

    /* IMPORTANT!!!
     * Inform the graphics library that you are ready with the flushing*/
    lv_disp_flush_ready(disp_drv);
}

static bool DEMO_ReadTouch(lv_indev_drv_t * indev_drv, lv_indev_data_t *data)
{
	static uint16_t x,y;
	__IO TS_StateTypeDef  ts;

	BSP_TS_GetState((TS_StateTypeDef *)&ts);

	if((ts.touchX[0] >= BSP_LCD_GetXSize()) ||(ts.touchY[0] >= BSP_LCD_GetYSize()) )
	{
		ts.touchX[0] = 0;
		ts.touchY[0] = 0;
	}
	x = ts.touchX[0];
	y = ts.touchY[0];
	y=240-y;

	data->state = LV_INDEV_STATE_REL;
	if(0!=ts.touchDetected)
	{
		data->state = LV_INDEV_STATE_PR;
	}
    data->point.x = y;
    data->point.y = x;

	return false;
}
